/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import { expect } from '@jest/globals';
import * as fs from 'fs';
import { copy, readdirSync } from 'fs-extra';
import * as path from 'path';
import { resolve } from 'path';

import { FileUtil } from '../../src/utils/file-util';

import { appRoot, initByStageEmptyApp, initExecuteCommand, runHvigor, runShouldFail } from './common/common';
import { ModuleJsonModifier } from './common/modifier/module-json-modifier';
import { GeneralDeviceType, SyscapJsonModifier } from './common/modifier/syscap-json-modifier';
import { Probes } from './common/probes';

describe('Syscap Test', () => {
  test.concurrent('Syscap test - basic', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@SyscapTransform',
        });
        const result = runHvigor(dir, commands);

        // run successful
        expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();

        // 检查syscap产物
        const probe = new Probes(dir, resolve(dir, 'entry'));
        const buildOutput = readdirSync(probe.getIntermediatesSysCap());

        expect(buildOutput.sort()).toEqual([
          'rpcid.json',
          'RPCID.sc'
        ].sort());
      }
    });
  });

  test.concurrent('Syscap test - no custom', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap-no-custom'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@SyscapTransform',
          log: 'i'
        });
        const result = runHvigor(dir, commands);

        // run successful
        expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
      }
    });
  });

  test.concurrent('Syscap test - deviceType incorrect', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const moduleJsonOpt = new ModuleJsonModifier(dir, 'entry');
        moduleJsonOpt.setDeviceType(['default']).outputSync();
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@SyscapTransform',
          log: 'i'
        });

        runShouldFail(dir, commands, 'Make sure the \'general\' field is contained in the syscap.json file');
      }
    });
  });

  // SyscapTransform任务增量
  test.concurrent('Syscap test - validate incremental', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {

        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@SyscapTransform',
          log: 'i'
        });

        const resultFirst = runHvigor(dir, commands);
        expect(resultFirst.stdout).toContain('Finished :entry:default@SyscapTransform...');
        expect(resultFirst.stdout).toContain('BUILD SUCCESSFUL');

        const resultIncremental = runHvigor(dir, commands);
        expect(resultIncremental.stdout).toContain('UP-TO-DATE :entry:default@SyscapTransform...');
        expect(resultIncremental.stdout).toContain('BUILD SUCCESSFUL');

        await copy(resolve(appRoot(), 'test/resources/extra/syscap_new'), resolve(dir, 'entry/src/main'));
        const syscapIntermediatePath = 'entry/build/default/intermediates/syscap';
        if (fs.existsSync(path.resolve(dir, syscapIntermediatePath))) {
          FileUtil.deleteFile(path.resolve(dir, syscapIntermediatePath));
        }
        const resultWithDeleteOneSyscap = runHvigor(dir, commands);
        expect(resultWithDeleteOneSyscap.stdout).toContain('Finished :entry:default@SyscapTransform...');
        expect(resultWithDeleteOneSyscap.stdout).toContain('BUILD SUCCESSFUL');
      }
    });
  });

  // 纯N设备场景校验：module.json5中deviceType为空且syscap.json中general为空时 构建成功
  test.concurrent('Syscap test - Only N device', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap_new'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@PreCheckSyscap',
          log: 'i'
        });

        const moduleJsonOpt = new ModuleJsonModifier(dir, 'entry');
        moduleJsonOpt.setDeviceType([]).outputSync();
        const syscapJsonModifier = new SyscapJsonModifier(dir, 'entry');
        syscapJsonModifier.setGeneralDevice([]).outputSync();
        expect(runHvigor(dir, commands).stdout).toContain('BUILD SUCCESSFUL');
        syscapJsonModifier.setGeneralDevice([GeneralDeviceType.default]).outputSync();
        runShouldFail(dir, commands, 'The value of \'general\' in the syscap.json file must be the same as');
      }
    });
  });

  // 1+8设备场景,module.json5中deviceType不为空,若syscap.json5中general字段配置与deviceType字段配置不一致则校验报错
  test.concurrent('Syscap test - Pre check for 1+8 device', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/syscap_new'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry',
          tasks: 'default@PreCheckSyscap',
          log: 'i'
        });

        const moduleJsonOpt = new ModuleJsonModifier(dir, 'entry');
        moduleJsonOpt.setDeviceType(['default']).outputSync();
        const syscapJsonModifier = new SyscapJsonModifier(dir, 'entry');
        syscapJsonModifier.setGeneralDevice([GeneralDeviceType.default]).outputSync();
        const resultSuccess = runHvigor(dir, commands);
        expect(resultSuccess.stdout).toContain('Finished :entry:default@PreCheckSyscap...');
        expect(resultSuccess.stdout).toContain('BUILD SUCCESSFUL');

        syscapJsonModifier.setGeneralDevice([GeneralDeviceType.tablet]).outputSync();
        runShouldFail(dir, commands, ' its value must be the same as the value of');
      }
    });
  });
});
